#ifndef __DALELIB_MD3_H__
#define __DALELIB_MD3_H__

#include <assert.h>
#include <string>
#include <vector>
#include <iostream>
#include <fstream>
using namespace std;

#include <dalelib/graphics.h>
#include <dalelib/maths.h>

namespace dalelib
{

//********************** structures *******************************
#define MD3VERSION (15)


class MD3Model
{
private:

	typedef enum
	{
		BOTH_DEATH1, BOTH_DEAD1, BOTH_DEATH2, BOTH_DEAD2, BOTH_DEATH3, BOTH_DEAD3, TORSO_GESTURE, TORSO_ATTACK, TORSO_ATTACK2, TORSO_DROP, TORSO_RAISE, TORSO_STAND, TORSO_STAND2, LEGS_WALKCR, LEGS_WALK, LEGS_RUN, LEGS_BACK, LEGS_SWIM, LEGS_JUMP, LEGS_LAND, LEGS_JUMPB, LEGS_LANDB, LEGS_IDLE, LEGS_IDLECR, LEGS_TURN, MAX_ANIMATIONS
	} AnimNumber;

	struct BoneFrame
	{
		v3 mins;
		v3 maxs;
		v3 position;
		float scale;
		char  creator[16];
	};
	struct Triangle { int v[3]; };
	struct TexCoord { v2 _uv; };
	struct Vertex { v3 _pos, _nrm; };
	struct Skin { char name[68]; };

	struct MD3Mesh
	{
		Vertex *_frames;
		Triangle *_triangles;
		TexCoord *_texcoords;
		Vertex *_vertices;
		Skin *_skins;

		unsigned int _num_frames;
		unsigned int _num_triangles;
		unsigned int _num_vertices;
		unsigned int _num_skins;

		MD3Mesh()
			: _frames(0)
			, _triangles(0)
			, _texcoords(0)
			, _vertices(0)
			, _skins(0)
//			texture		= NULL;
		{ }

		~MD3Mesh()
		{
			delete [] _frames;
			delete [] _triangles;
			delete [] _texcoords;
			delete [] _vertices;
			delete [] _skins;
		}
	};

	struct MD3Link { string _name; m4 _mat; MD3Model *_model; };

	MD3Mesh *_meshes;
	MD3Link *_links;
	unsigned int _num_frames;
	unsigned int _num_meshes;
	unsigned int _num_links;

public:

	MD3Model() { }

	~MD3Model()
	{
		delete [] _meshes;
		delete [] _links;
	}

//	int getNumFrames() { return _frames.size(); }

	void transform(const m4 &_Mat);
	void calculateNormalTable();
	int load(const string _FileName);
	int link(string _TagName, MD3Model *_Model);
	void unlink(string _TagName);
	void animate(const int _Start, const int _End, int &_Frame, float &_Lerp);
	void draw(const unsigned int _Frame1,const unsigned int _Frame2,const float _Lerp);
	void render();
};

//*********************************************************************
class MD3Character
{
private:

	MD3Model _head, _upper, _lower;

public:

	void loadPlayer(string _Path, string _Skin="default");
	void transform(const m4 &_Mat);
	void render();
};

} // namespace dalelib

#endif
